#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include "common.h"
#include "NDA_driver.h"
#include "HBA_driver.h"

MODULE_AUTHOR("Arkins");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Trusted Path.");

typedef struct tagModuleCtx {
    const char *name;
    int (*init)(void);
    void (*exit)(void);
} MODULE_CTX;

#define MODULE_CTX_LEN 2
const MODULE_CTX g_moduleCtx[MODULE_CTX_LEN] = {
    { "HBA_Driver", HBA_DriverInit, HBA_DriverExit },
    { "NDA_Driver", NDA_DriverInit, NDA_DriverExit },
};

static void TP_ReallyExit(int start)
{
    int idx;
    if (start >= MODULE_CTX_LEN) {
        start = MODULE_CTX_LEN - 1;
    } else if (start < 0) {
        return;
    }
    for (idx = start; idx >= 0; idx--) {
        g_moduleCtx[idx].exit();
    }
}

static int __init TP_Init(void)
{
    int idx = 0, ret = 0, errorFlag = 0;

    for (idx = 0; idx < MODULE_CTX_LEN; idx++) {
        ret = g_moduleCtx[idx].init();
        if (ret != TP_OK) {
            TP_LOG_ERROR("Init module %s failed, ret = %d", g_moduleCtx[idx].name, ret);
            errorFlag = 1;
            break;
        }
        TP_LOG_INFO("Module %s is initialized successfully", g_moduleCtx[idx].name);
    }
    if (errorFlag) {
        TP_ReallyExit(idx - 1);
    }
    return TP_OK;
}

static void __exit TP_Exit(void)
{
    TP_ReallyExit(MODULE_CTX_LEN - 1);
}

module_init(TP_Init)
module_exit(TP_Exit)
